home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et-2_2.lha / et2.2 / src / GraphView.C < prev    next >
C/C++ Source or Header  |  1990-12-06  |  12KB  |  591 lines

  1. //$GraphView,GraphNode,GraphNodeMover,GraphPath,GraphReference$
  2.  
  3. #include "ObjList.h"
  4. #include "IdDictionary.h"
  5. #include "OrdColl.h"
  6. #include "Dialog.h"
  7. #include "GraphView.h"
  8.  
  9. //---- GraphNode -------------------------------------------------------------
  10.  
  11. MetaImpl(GraphNode, (TP(constrainingNodes), TP(nonTreeOutEdges), T(inEdges), 0));
  12.  
  13. GraphNode::GraphNode(int id, Collection *cp) : TreeNode(id, cp)
  14.     constrainingNodes= 0; 
  15.     nonTreeOutEdges= 0;
  16.     inEdges= 0; 
  17. }
  18.  
  19. GraphNode::~GraphNode()
  20. {
  21.     SafeDelete(nonTreeOutEdges);
  22.     Object *op= Image();
  23.     if (op) {
  24.     op->FreeAll();
  25.     SafeDelete(op);
  26.     }
  27. }
  28.  
  29. VObject *GraphNode::Image()
  30. {
  31.     Collection *cp= GetList();
  32.     if (cp)
  33.     return (VObject*)(cp->At(0));
  34.     return 0;
  35. }
  36.  
  37. int GraphNode::CalcShift()
  38. {
  39.     Point origin= contentRect.origin;
  40.     
  41.     if (InCalcShift()) {
  42.     Warning("CalcShift", "cycle in graph");
  43.     return contentRect.origin.x;
  44.     }
  45.     SetFlag(eGraphInCalc);
  46.     if (!IsPositionSet()) {
  47.     SetFlag(eGraphPosSet); 
  48.     if (constrainingNodes) {
  49.         Iter next(constrainingNodes->MakeIterator());
  50.         GraphNode *gp;
  51.         while (gp= (GraphNode*)next()) 
  52.         origin.x = max(origin.x, gp->CalcShift());
  53.         //if (origin.x != contentRect.origin.x)
  54.         origin.x += 2*(Gap().x);
  55.     }
  56.     SafeDelete(constrainingNodes);
  57.     }
  58.     if (origin != contentRect.origin)
  59.     SetOrigin(origin);   
  60.         
  61.     ResetFlag(eGraphInCalc);
  62.     return contentRect.origin.x+contentRect.extent.x;
  63. }
  64.  
  65. void GraphNode::AddNonTreeOutEdge(GraphNode *gp)
  66. {
  67.     if (nonTreeOutEdges == 0)
  68.     nonTreeOutEdges= new OrdCollection;
  69.     nonTreeOutEdges->Add(gp);
  70. }
  71.  
  72. void GraphNode::AddConstrainingNode(GraphNode *gp)
  73. {
  74.     if (constrainingNodes == 0)
  75.     constrainingNodes= new OrdCollection;
  76.     constrainingNodes->Add(gp);
  77. }
  78.  
  79. void GraphNode::Draw(Rectangle r)
  80. {
  81.     Image()->DrawAll(r, FALSE);
  82. }
  83.  
  84. void GraphNode::DrawConnections()
  85. {
  86.     TreeNode::DrawConnections();
  87.     if (nonTreeOutEdges) {
  88.     VObject *image= Image();
  89.     Point p1= image->contentRect.E();
  90.     Iter next(nonTreeOutEdges);
  91.     GraphNode *gp;
  92.     while (gp= (GraphNode*)next()) 
  93.         GrLine(p1, gp->Image()->contentRect.W());
  94.     }
  95. }
  96.  
  97. void GraphNode::Export(ostream &s)
  98. {
  99.     // leave node
  100.     if ((GetList()->Size() + (nonTreeOutEdges ? nonTreeOutEdges->Size() : 0)) == 1)
  101.     return;
  102.     
  103.     GraphNode *gp;
  104.     int i= 0;
  105.     if (GetList()) {
  106.     Iter next1(GetList());
  107.     while (gp= (GraphNode*)next1()) {
  108.         if (i++ == 0) // the image of the node itself
  109.         s << gp->AsString() << ": "; 
  110.         else
  111.         s << gp->Image()->AsString() SP;
  112.     } 
  113.     } 
  114.     if (nonTreeOutEdges) {
  115.     Iter next2(nonTreeOutEdges);
  116.     while (gp= (GraphNode*)next2()) 
  117.         s << gp->Image()->AsString() SP;
  118.     }
  119.     s NL;
  120. }
  121.  
  122. //---- GraphNodeMover -------------------------------------------------------------
  123.  
  124. class GraphNodeMover: public Command {
  125.     GraphView *gvp;
  126.     GraphNode *gnp;
  127.     VObject *item;
  128.     GrCursor oldcursor;
  129.     Point delta;
  130. public:
  131.     GraphNodeMover(GraphView *g, GraphNode *v) : Command(cIdNone, "move node")
  132.     { gvp= g; gnp= v; item= gnp->Image(); delta= 0; }
  133.     void TrackFeedback(Point, Point, bool);
  134.     Command *TrackMouse(TrackPhase, Point, Point, Point);
  135.     void DoIt();
  136.     void UndoIt();
  137. };
  138.  
  139. void GraphNodeMover::TrackFeedback(Point anchorPoint, Point nextPoint, bool)
  140. {
  141.     item->Outline(nextPoint - anchorPoint);
  142. }
  143.  
  144. Command *GraphNodeMover::TrackMouse(TrackPhase tp, Point ap, Point, Point np)
  145. {
  146.     switch (tp) {
  147.     case eTrackPress:
  148.     oldcursor= GrGetCursor();
  149.     break;
  150.     case eTrackMove:
  151.     GrSetCursor(eCrsMoveHand);
  152.     break;
  153.     case eTrackRelease:
  154.     delta= np-ap;
  155.     GrSetCursor(oldcursor);
  156.     break;
  157.     default:
  158.     break;
  159.     }
  160.     return this;
  161.  
  162. }
  163.  
  164. void GraphNodeMover::DoIt()
  165. {
  166.     item->Move(delta);
  167.     gnp->contentRect+= delta;
  168.     gvp->CalcExtent();
  169.     gvp->ForceRedraw();
  170. }
  171.  
  172. void GraphNodeMover::UndoIt()
  173. {
  174.     item->Move(-delta);
  175.     gnp->contentRect-= delta;
  176.     gvp->CalcExtent();
  177.     gvp->ForceRedraw();
  178. }
  179.  
  180. //---- GraphView -----------------------------------------------------------------
  181.  
  182. MetaImpl(GraphView, (TP(nodes), TP(paths), TP(refs), 0));
  183.  
  184. GraphView::GraphView(EvtHandler *dp) : TreeView(dp)
  185. {
  186.     nodes= new IdDictionary; 
  187.     connType= eTCDiagonal;
  188.     paths= new OrdCollection;
  189.     refs= new OrdCollection;
  190. }
  191.  
  192. GraphView::~GraphView()
  193. {
  194.     nodes->FreeValues();
  195.     SafeDelete(nodes);
  196.     SafeDelete(paths);
  197.     SafeDelete(refs);
  198. }
  199.  
  200. void GraphView::Draw(Rectangle r)
  201. {
  202.     DictIterValues next(nodes);
  203.     register GraphNode *np;
  204.     
  205.     View::Draw(r);
  206.     if (connType != eTCNone)
  207.     while (np= (GraphNode*) next()) 
  208.         np->DrawConnections();
  209.     
  210.     DrawPaths(r);
  211.     DrawReferences(r);
  212.         
  213.     next.Reset();
  214.     while (np= (GraphNode*) next()) {
  215.     VObject *vp= np->Image();
  216.     if (vp && vp->contentRect.Intersects(r))
  217.         vp->DrawAll(r, vp == GetSelection());
  218.     }
  219. }
  220.  
  221. void GraphView::SetConnType(TreeConnection ct)
  222. {
  223.     if (ct != eTCNone && ct != eTCDiagonal)
  224.     return;  
  225.     connType= ct;
  226.     ForceRedraw();  
  227. }
  228.  
  229. GraphNode *GraphView::FindNode(Point lp)
  230. {
  231.     DictIterValues next(nodes);
  232.     GraphNode *np;
  233.     while (np= (GraphNode *)next()) {
  234.     VObject *vp= np->Image();
  235.     if (vp->ContainsPoint(lp))
  236.         return np;
  237.     } 
  238.     return 0;  
  239. }
  240.  
  241. Command *GraphView::DoLeftButtonDownCommand(Point lp, Token, int cl)
  242. {
  243.     GraphNode *np= FindNode(lp);
  244.     if (np)
  245.     return new TreeNodeSelector(np, cl);
  246.     return gNoChanges;  
  247. }
  248.  
  249. Command *GraphView::DoMiddleButtonDownCommand(Point lp, Token, int)
  250. {
  251.     GraphNode *np= FindNode(lp);
  252.     if (np)
  253.     return new GraphNodeMover(this, np);
  254.     return gNoChanges;  
  255. }
  256.  
  257. void GraphView::CalcExtent()
  258. {
  259.     DictIterValues next(nodes);
  260.     register GraphNode *np;
  261.     Rectangle r;
  262.     while (np= (GraphNode *)next()) 
  263.     r.Merge(np->Image()->contentRect);
  264.     SetExtent(r.extent+Point(200)); 
  265. }
  266.  
  267. Iterator *GraphView::MakeSubPartsIter(Object *)
  268. {
  269.     AbstractMethod("MakeSubPartsIter");
  270.     return 0;  
  271. }
  272.  
  273. Iterator *GraphView::MakeChildrenIter(Object *op)
  274. {
  275.     return MakeSubPartsIter(op);
  276. }
  277.  
  278. VObject *GraphView::DoCreateRoot()
  279. {
  280.     return new TextItem("Root");
  281. }
  282.  
  283. VObject *GraphView::DoCreateDialog()
  284. {
  285.     return 0;
  286. }
  287.  
  288. VObject *GraphView::AssociatedVObject(Object *op)
  289. {
  290.     GraphNode *gp= (GraphNode*) nodes->AtKey(op);
  291.     if (gp)
  292.     return gp->Image();
  293.     return 0;      
  294. }
  295.     
  296. GraphNode *GraphView::AssociatedGraphNode(Object *op)
  297. {
  298.     return (GraphNode*) nodes->AtKey(op);
  299. }
  300.  
  301. void GraphView::SetGraph(GraphNode *root, bool)
  302. {
  303.     DictIterValues next(nodes);
  304.     GraphNode *np;
  305.     
  306.     while (np= (GraphNode *)next()) {
  307.     np->SetContainer(this);
  308.     np->Enable();
  309.     }
  310.     // calculate tree layout
  311.     root->CalcExtent();
  312.     root->SetOrigin(GetOrigin());
  313.     next.Reset();
  314.     while (np= (GraphNode *)next()) 
  315.     np->CalcShift();
  316.     CalcExtent();
  317.     ForceRedraw();
  318. }
  319.  
  320. void GraphView::EmptyGraph()
  321. {
  322.     SetSelection(0);
  323.     nodes->FreeValues();
  324. }
  325.  
  326. GraphNode *GraphView::BuildGraphDFS(Object *np)
  327. {
  328.     Object *subNode;
  329.     GraphNode *gp;
  330.     
  331.     if (gp= (GraphNode*) nodes->AtKey(np)) 
  332.     return gp;
  333.     
  334.     GraphNode *node= new GraphNode;
  335.     node->AddNode(NodeAsVObject(np));
  336.     nodes->AtKeyPut(np, node); // register node in dictionary
  337.     Iterator *it= MakeSubPartsIter(np);
  338.     
  339.     if (it) {
  340.     Iter next(it);
  341.     
  342.     while (subNode= next()) {            
  343.         // node already occurred hence must be a nonTreeOutEdge
  344.         if (gp= (GraphNode*) nodes->AtKey(subNode)) { // node already occurred, -> nonTreeOutEdge
  345.         node->AddNonTreeOutEdge(gp);
  346.         gp->AddConstrainingNode(node);
  347.         } else {
  348.         gp= BuildGraphDFS(subNode);
  349.         node->AddNode(gp);
  350.         }
  351.         gp->AddInEdge(node);
  352.     }
  353.     }
  354.     return node;    
  355. }   
  356.  
  357. void GraphView::BuildGraphBFS(Object *op)
  358. {
  359.     ObjList q;          // queue for breadth first search
  360.     GraphNode *gnp, *snp;
  361.     Object *subnode, *node;
  362.     
  363.     q.Add(op);
  364.     while (q.Size() > 0) {
  365.     node= q.RemoveFirst();
  366.     if ((gnp= (GraphNode *) nodes->AtKey(node)) == 0) {
  367.         gnp= new GraphNode;
  368.         nodes->AtKeyPut(node, gnp);
  369.         gnp->AddNode(NodeAsVObject(node));
  370.     }
  371.     Iterator *it= MakeSubPartsIter(node);
  372.     if (it) {
  373.         Iter next(it);
  374.         while (subnode= next()) {
  375.         // node was already visited
  376.         if (snp= (GraphNode*)nodes->AtKey(subnode)) {
  377.             gnp->AddNonTreeOutEdge(snp);
  378.             snp->AddConstrainingNode(gnp);
  379.         } else {
  380.             snp= new GraphNode();
  381.             snp->AddNode(NodeAsVObject(subnode));
  382.             gnp->AddNode(snp);
  383.             nodes->AtKeyPut(subnode, snp);
  384.             q.Add(subnode);
  385.         }
  386.         snp->AddInEdge(gnp);
  387.         }
  388.     }
  389.     }
  390. }   
  391.  
  392. GraphNode *GraphView::FindRoot()
  393. {
  394.     OrdCollection *oc= new OrdCollection();    
  395.     DictIterValues next(nodes);
  396.     GraphNode *np, *root;
  397.  
  398.     while (np= (GraphNode *)next())
  399.     if (np->NumInEdges() == 0)
  400.         oc->Add(np);
  401.         
  402.     if (oc->Size() == 1) {
  403.     root= (GraphNode*)oc->First();
  404.     SafeDelete(oc);
  405.     return root;
  406.     }
  407.     // create artificial root
  408.     VObject *vop= DoCreateRoot();
  409.     oc->AddFirst(vop);
  410.     root= new GraphNode(cIdNone, oc);
  411.     nodes->AtKeyPut(vop, root); 
  412.     return root;
  413. }
  414.  
  415. void GraphView::DrawPaths(Rectangle r)
  416. {
  417.     Iter next(paths);
  418.     GraphPath *gp;
  419.     while (gp= (GraphPath*)next()) 
  420.     gp->Draw(r);
  421. }
  422.  
  423. void GraphView::AddPath(GraphPath *p)
  424. {
  425.     paths->Add(p);
  426.     InvalidateRect(p->BBox());
  427. }
  428.  
  429. GraphPath *GraphView::RemovePath(GraphPath *p)
  430. {
  431.     GraphPath *gp;
  432.     gp= (GraphPath*)paths->RemovePtr(p);
  433.     if (gp)
  434.     InvalidateRect(p->BBox());
  435.     return gp;
  436. }
  437.  
  438. void GraphView::RemoveAllPaths()
  439. {
  440.     paths->FreeAll();
  441.     paths->Empty(0);
  442.     ForceRedraw();
  443. }
  444.  
  445. void GraphView::DrawReferences(Rectangle r)
  446. {
  447.     Iter next(refs);
  448.     GraphReference *gp;
  449.     while (gp= (GraphReference*)next()) 
  450.     gp->Draw(r);
  451. }
  452.  
  453. void GraphView::AddReference(GraphReference *p)
  454. {
  455.     refs->Add(p);
  456.     InvalidateRect(p->BBox());
  457. }
  458.  
  459. GraphReference *GraphView::RemoveReference(GraphReference *p)
  460. {
  461.     GraphReference *gp;
  462.     gp= (GraphReference*)refs->RemovePtr(p);
  463.     if (gp)
  464.     InvalidateRect(p->BBox());
  465.     return gp;
  466. }
  467.  
  468. void GraphView::RemoveAllReferences()
  469. {
  470.     refs->FreeAll();
  471.     refs->Empty(0);
  472.     ForceRedraw();
  473. }
  474.  
  475. //---- GraphPath ------------------------------------------------------------
  476.  
  477. GraphPath::GraphPath(GraphView *g, Collection *n, Ink *i, int w, bool f)
  478. {
  479.     nodes= n;
  480.     free= f;
  481.     gvp= g;
  482.     width= w;
  483.     ink= i;
  484. }
  485.         
  486. GraphPath::~GraphPath()
  487. {
  488.     if (free)
  489.     SafeDelete(nodes);
  490. }
  491.     
  492. void GraphPath::Draw(Rectangle)
  493. {
  494.     Object *op;
  495.     VObject *image;
  496.     Iter next(nodes);
  497.  
  498.     for (int i= 0; op= next(); i++) {
  499.     image= gvp->AssociatedVObject(op);
  500.     if (!image)
  501.         continue;//Error("Draw", "node in GraphPath without representation");
  502.     GrSetPenNormal();
  503.     GrStrokeRect(image->contentRect.Expand(1));
  504.     GrSetPenSize(width);
  505.     GrSetPenPattern(ink);
  506.     if (i == 0)
  507.         GrMoveto(image->contentRect.Center());
  508.     else
  509.         GrLineto(image->contentRect.Center());
  510.     }
  511. }
  512.  
  513. Rectangle GraphPath::BBox()
  514. {
  515.     Rectangle r;
  516.     Object *op;
  517.     VObject *image;
  518.     Iter next(nodes);
  519.     while (op= next()) 
  520.     if (image= gvp->AssociatedVObject(op))
  521.         r.Merge(image->contentRect.Expand(4));
  522.     return r;
  523. }
  524.  
  525. //---- GraphReference ------------------------------------------------------------
  526.  
  527. GraphReference::GraphReference(GraphView *g, Object *op, Collection *n, Ink *i, int w, bool f)
  528. {
  529.     nodes= n;
  530.     free= f;
  531.     gvp= g;
  532.     width= w;
  533.     ink= i;
  534.     referto= op;
  535. }
  536.         
  537. GraphReference::~GraphReference()
  538. {
  539.     if (free)
  540.     SafeDelete(nodes);
  541. }
  542.     
  543. void GraphReference::Draw(Rectangle)
  544. {
  545.     Object *op;
  546.     VObject *image, *opimage;
  547.  
  548.     Iter next(nodes);
  549.     opimage= gvp->AssociatedVObject(referto);
  550.     if (!opimage)
  551.     return;
  552.     GrSetPenNormal();
  553.     GrStrokeRect(opimage->contentRect.Expand(1)); 
  554.        
  555.     for (int i= 0; op= next(); i++) {
  556.     image= gvp->AssociatedVObject(op);
  557.     if (!image)
  558.         continue;//Error("Draw", "node in GraphPath without representation");
  559.     GrSetPenNormal();
  560.     GrStrokeRect(image->contentRect.Expand(1));
  561.     DrawConnection(i, opimage, image);
  562.     }
  563. }
  564.  
  565. void GraphReference::DrawConnection(int, VObject *from, VObject *to)
  566. {
  567.     GrSetPenSize(width);
  568.     GrSetPenPattern(ink);
  569.     Point p1= from->contentRect.Center();
  570.     Point p2= to->contentRect.Center();
  571.     GrLine(p1, p2);
  572. }
  573.  
  574. Rectangle GraphReference::BBox()
  575. {
  576.     Rectangle r;
  577.     Object *op;
  578.     VObject *image, *opimage;
  579.     Iter next(nodes);
  580.   
  581.     opimage= gvp->AssociatedVObject(referto);
  582.     while (opimage && (op= next())) {
  583.     if (image= gvp->AssociatedVObject(op)) {
  584.         r.Merge(opimage->contentRect.Expand(4));
  585.         r.Merge(image->contentRect.Expand(4));
  586.     }
  587.     }
  588.     return r;
  589. }
  590.